#[derive(FromForm)]
struct UserForm {
    user: String,
    password: String
}

#[post("/user_login", data = "<user_form>")]
fn user_login(user_form: Form<UserForm>, mut cookies: Cookies, state: State<MySqlDriver>) -> String {
    let mut except_vec: Vec<char> = Vec::new();
    except_vec.push('\'');
    except_vec.push('"');
    except_vec.push('\\');
    let user: HoString = HoString::copy_str(user_form.user.as_str());
    let password: HoString = HoString::copy_str(user_form.password.as_str());
    if user.length() == 0 || password.length() == 0 {
        return "fail:表单中存在空值".to_string();
    } else if user.contains_char_vec(except_vec.clone(), 0) == true ||
                password.contains_char_vec(except_vec.clone(), 0) == true {
        return "fail:表单值不能包含引号和斜杠".to_string();
    } else {
        let pool_result: Result<Pool, mysql::Error> = Pool::new(state.driver.as_str());
        let pool: Pool;
        if let Ok(p) = pool_result {
            pool = p;
        } else {
            return "fail:无法建立数据库连接".to_string();
        }
        let conn_res: Result<PooledConn, mysql::Error> = pool.get_conn();
        let mut conn: PooledConn;
        if let Ok(res) = conn_res {
            conn = res;
        } else {
            return "fail:无法获取数据库连接".to_string();
        }
        let sql: String = format!("SELECT `id`, `account`, `email`, `tel`, `alipay_account`, \
            `password`, `alipay_name`, `qq_number`, `push_id` \
            FROM `user` WHERE `account` = '{}' ORDER BY `id` DESC LIMIT 1", user.to_str());
        let result_rows: Result<Option<Row>, mysql::Error> = conn.query_first(sql.clone());
        let row: Row;
        match result_rows {
            Ok(row_op) => {
                match row_op {
                    Some(r) => row = r,
                    None => return "fail:用户不存在".to_string()
                }
            },
            Err(err) => {
                dbg!(err);
                return "fail:数据查询失败".to_string();
            }
        }
        if row.len() == 0 {
            return "fail:账号不存在".to_string();
        }
        let mut password: String = String::new();
        let password_op: Option<String> = row.get("password");
        if let Some(p) = password_op {
            password = p;
        }
        let verify_result: BcryptResult<bool> = verify(user_form.password.clone(), password.as_str());
        if let Ok(v) = verify_result {
            if v {
                let id_op: Option<String> = row.get("id");
                let account_op: Option<String> = row.get("account");
                let email_op: Option<String> = row.get("email");
                let tel_op: Option<String> = row.get("tel");
                let alipay_account_op: Option<String> = row.get("alipay_account");
                let alipay_name_op: Option<String> = row.get("alipay_name");
                let qq_number_op: Option<String> = row.get("qq_number");
                let push_id_op: Option<String> = row.get("push_id");
                if let Some(id) = id_op {
                    cookies.add(Cookie::new("id", id));
                }
                if let Some(account) = account_op {
                    cookies.add(Cookie::new("account", account));
                }
                if let Some(email) = email_op {
                    cookies.add(Cookie::new("email", email));
                }
                if let Some(tel) = tel_op {
                    cookies.add(Cookie::new("tel", tel));
                }
                if let Some(alipay_account) = alipay_account_op {
                    cookies.add(Cookie::new("alipay_account", alipay_account));
                }
                if let Some(alipay_name) = alipay_name_op {
                    cookies.add(Cookie::new("alipay_name", alipay_name));
                }
                if let Some(qq_number) = qq_number_op {
                    cookies.add(Cookie::new("qq_number", qq_number));
                }
                if let Some(push_id) = push_id_op {
                    cookies.add(Cookie::new("push_id", push_id));
                }
                return "success:".to_string();
            } else {
                return "fail:账号或密码错误".to_string();
            }
        } else {
            return "fail:账号或密码错误".to_string();
        }
    }
}

#[get("/login")]
fn login() -> Response<'static> {
    let login_str: HoString = HoFile::read_file_all("web/login.html", "");
    let html: String = login_str.to_str().to_string().to_owned();
    let mut res = Response::new();
    res.set_header(ContentType::HTML);
    res.set_sized_body(Cursor::new(html));
    return res;
}
